home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / amok_lha / amok71.lha / Formula / Formula.dok next >
Text File  |  1993-08-15  |  21KB  |  541 lines

  1. ======================================================================
  2. Dokumentation zu dem Modul Formula V1.0             Stade, den 26.4.92
  3. ======================================================================
  4. :Contents.   Module to evaluate numeric expressions like
  5. :Contents.   "sin(x)/epsilon*(time-7.2E3)"
  6. :Author.     Stefan Salewski
  7. :Address.    Stefan Salewski, Stolper Weg 3, D-2160 Stade
  8. :Copyright.  © 1992 by Stefan Salewski
  9. :Language.   Oberon
  10. :Translator. Amiga-Oberon-Compiler V2.14d
  11. :Imports.    TurboFiles V2.1 (on this Disk, take Assemblerpart and
  12. :Imports.    Documentation from Amok#56
  13. :Imports.    RealConversions2 from Amok#58
  14. :Remark.     Compile it with options 881 and 68030 set if You use
  15. :Remark.     it on an A3000. This speed up the calculations
  16. :Remark.     Be careful if You turn off stackcheck, this module
  17. :Remark.     uses recursion!
  18. :History.    V1.0    3. MAY 1992
  19.  
  20. Fehlernummern: Formula.error enthält sie, wenn Evaluate() fehlschlägt.
  21. CONST
  22.   NoError*        = 0;
  23.   Overflow*       = 1;
  24.   DivisionByZero* = 2;
  25.   sqrtError*      = 3;
  26.   lnError*        = 4;
  27.   arcsinError*    = 5;
  28.   arccosError*    = 6;
  29.   artanhError*    = 7;
  30.   facError*       = 8;
  31.   rndError*       = 9;
  32.   entierError*    = 10;
  33.   powError*       = 11;
  34.   CompileError*   = 12;
  35.  
  36. Einige benutzte Datentypen, wichtig ist nur Formula:
  37. TYPE
  38.   String80  = ARRAY 80 OF CHAR;     (* nur für Fehlermeldungen *)
  39.   EText     = ARRAY 13 OF String80;
  40.   WriteProc = PROCEDURE(str:ARRAY OF CHAR);
  41.  
  42.   Formula   = RECORD (* Diesen Typ braucht man für Evaluate() *)
  43.                 error : INTEGER;
  44.               END;
  45.  
  46. Der den obigen Fehlernummern zugeordnete Fehlertext:
  47. CONST
  48.   ErrorText=EText('No Error',
  49.                   'Overflow: ABS(Result) >= MAX(LONGREAL)',
  50.                   'Division by Zero',
  51.                   'sqrt(x) only for x>=0',
  52.                   'ln(x) only for x>0',
  53.                   'arcsin(x) only for ABS(x)<=1',
  54.                   'arccos(x) only for ABS(x)<=1',
  55.                   'artanh(x) only for -1 < x < +1 ',
  56.                   'fac(x) only for x = {0,1,2,...,170}',
  57.                   'rnd(x) only for x = {1,2,3,...,MAX(INTEGER)}',
  58.                   'entier(x) only for ABS(x)<MAX(LONGINT)',
  59.                   'x^y: if x is negative, y must be an integer',
  60.                   'Error in Compile()'
  61.                  );
  62.  
  63. Die Prozeduren des Moduls alphabetisch sortiert:
  64. PROCEDURE ChangeValue(index: INTEGER; value: LONGREAL);
  65. PROCEDURE Compile(str: ARRAY OF CHAR; VAR formula: Formula): BOOLEAN;
  66. PROCEDURE DefineValue(name: ARRAY OF CHAR; value: LONGREAL;
  67.                       trash: BOOLEAN;
  68.                       comment: ARRAY OF CHAR): BOOLEAN;
  69. PROCEDURE DeleteSpaces(VAR str: ARRAY OF CHAR);
  70. PROCEDURE DisposeAllValues;
  71. PROCEDURE Divide(VAR input, name, expression, comment: ARRAY OF CHAR);
  72. PROCEDURE Evaluate(VAR formula: Formula; VAR res: LONGREAL): BOOLEAN;
  73. PROCEDURE FindValue(name: ARRAY OF CHAR; VAR x: LONGREAL;
  74.                     VAR comment: ARRAY OF CHAR): BOOLEAN;
  75. PROCEDURE GetIndex(name: ARRAY OF CHAR; VAR index: INTEGER): BOOLEAN;
  76. PROCEDURE LoadValues(filename: ARRAY OF CHAR): BOOLEAN;
  77. PROCEDURE RemoveValue(name: ARRAY OF CHAR): BOOLEAN;
  78. PROCEDURE SaveValues(filename: ARRAY OF CHAR): BOOLEAN;
  79. PROCEDURE Split(VAR str1, str2: ARRAY OF CHAR; c: CHAR): BOOLEAN;
  80. PROCEDURE WriteFunctions(p: WriteProc);
  81. PROCEDURE WriteValues(p: WriteProc);
  82.  
  83.  
  84. Inhalt:
  85. -------
  86. Aufgabe dieses Moduls ist es, mathematische Formeln, die als String
  87. vorliegen, zu berechnen. Dadurch wird es recht einfach mathematische
  88. Programme wie Funktionsplotter, "Taschenrechner", Programme die
  89. nummerisch Integrieren, Differentialgleichungen nummerisch lösen, usw.
  90. zu schreiben. Man braucht im Prinzip nur die Formel in Form eines
  91. Strings einzulesen, sie mit Compile() zu überprüfen und kann sie dann
  92. (eventuell mehrmals mit geänderten Zahlenwerten) mit Evaluate()
  93. berechnen. Diese Berechnung geht recht schnell, auf einem A3000 dauerd
  94. die Berechnung einer durchschnittlichen Formel nur ca. eine
  95. tausendstel Sekunde. (Auf einem Rechner ohne Arithmetikprozessor
  96. dauert die Berechnung natürlich etwas länger, da diese Rechner mit
  97. LONGREAL-Zahlen nur langsam Rechnen können.)
  98.  
  99.  
  100. COPYRIGHT
  101. ---------
  102. Dieses Modul befindet sich nicht in der Public Domain! Alle Rechte an
  103. diesem Modul liegen beim Autor. Diese Version von FORMULA darf nur in
  104. Verbindung mit einer unveränderten AMOK-Diskette verbreitet werden.
  105. Die Aufnahme von FORMULA auf eine andere Diskettenserie oder irgendein
  106. sonstiger Vertrieb dieses Moduls ist nur mit meiner schriftlichen
  107. Genehmigung erlaubt. Insbesondere sind Modifikationen des Moduls oder
  108. der Dokumentation, der Abdruck oder die Übersetzung und jede andere
  109. Vervielfältigung von Modul und Dokumentation untersagt. Grundsätzlich
  110. darf für eine Diskette auf der sich Formula befindet nur der Preis der
  111. Leerdiskette zuzüglich einer geringen Kopiergebühr verlangt werden.
  112. (In der Regel kostet eine FD-Diskette DM 1.60 + Porto) Der Autor
  113. behält sich das Recht vor, einzelnen Firmen oder Personen das Recht
  114. auf Verbreitung dieses Produktes zu untersagen!
  115.  
  116. Dieses Modul ist FREEWARE. Das heißt es kann (und sollte) für die
  117. Entwicklung eigener Rechenprogramme benutzt werden, solange die damit
  118. erzeugten Programme nicht kommerziell vermarktet werden. Wer Formula
  119. für kommerzielle Produkte verwenden will muß vorher meine schriftliche
  120. Genehmigung einholen.
  121.  
  122. Meine Anschrift:
  123. Stefan Salewski
  124. Stolper Weg 3
  125. D-2160 Stade
  126. (Germany)
  127.  
  128.  
  129. Einführung
  130. ----------
  131. Befor ich auf die einzelnen Prozeduren des Moduls eingehe möchte ich
  132. einen kurzen Überblick über das grundlegende Konzept des Moduls geben.
  133. Dieses Modul kann praktisch jede mathematisvhe Formel berechnen. Dabei
  134. dürfen die Formeln auch durch Namen bezeichnete Konstanten und
  135. Variablen enthalten. Ausdrüche wie etwa
  136.  
  137. 1.23*sin(4.5)+Pi/epsilon
  138. arcsin(3/2)-2.7E3^3.2
  139.  
  140. können berechnet werden.
  141.  
  142. Die Ausdrücke dürfen folgendes enthalten:
  143. Die mathematischen Operatoren +,-,*,/,^
  144. Zahlenkonstanten wie 1.23E-5, 3.14, 2
  145. Elementare Funktionen wie sin, exp, arctan
  146. Klammern (),[],{}
  147. Werte (engl. Values)
  148. (Leerzeichen in mathematischen Ausdrücken sind nicht erlaubt.)
  149.  
  150.  
  151. Operatoren
  152. ----------
  153. Es existieren 5 mathematische Operatoren:
  154.  
  155. Symbol  Bedeutung  Priorität
  156. ----------------------------
  157.  +      Plus        1
  158.  -      Minus       1
  159.  *      Mal         2
  160.  /      Durch       2
  161.  ^      Hoch        3
  162.  
  163. Mal und Durch haben also Vorrang vor Plus und Minus. Der
  164. Potenzoperator ^ hat Vorrang vor den übrigen vier Operatoren. (Dies
  165. ist allgemein üblich und unter den Begriff "Punkt- vor Strichrechnung"
  166. bekannt.) Um andere Prioritäten festzulegen können selbstverständlich
  167. Klammern benutzt werden. Neben () können auch [] und {} benutzt
  168. werden. Das Weglassen des Multiplizieroperators ist nicht erlaubt. Man
  169. darf also statt 4*Pi*e0 nicht 4Pie0 schreiben. (Manchmal findet man in
  170. Büchern Ausdrücke wie "1/4 Pi e0". Gemeint ist damit "1/(4*Pi*e0)".
  171. Den weggelassenen Multiplikationsoperatoren wird also eine höhere
  172. Priorität als dem Divisionsoperator / zugeordnet. Da das Weglassen von
  173. Operatoren nicht erlaubt ist und Mal und Durch gleiche Priorität haben
  174. muß man also "1/(4*pi*e0)" schreiben.)
  175.  
  176.  
  177. Elementare mathematische Funktionen
  178. -----------------------------------
  179. In wesentlichen handelt es sich hierbei um bekannte Funktionen, die
  180. von dem mathematischen Koprozessor oder der MathIEEEDoubTrans.library
  181. berechnet werden. Argumente oder Ergebnisse von Winkelfunktionen wie
  182. sin() oder arctan() sind immer auf Radiant bezogen.
  183.  
  184. DegToRad()
  185. ----------
  186. Wandelt einen in Grad angegebenen Winkel in Radiant um. Das gleiche
  187. erreicht man durch "*Pi/180"
  188.  
  189. RND()
  190. -----
  191. Produziert Zufallszahlen. Das Argument muß eine GANZE Zahl zwischen 1
  192. und MAX(INTEGER) sein. RND(n) liefert eine Zufallszahl zwischen 0 und
  193. (n-1). (RND(6)+1) simuliert also einen Würfel.
  194.  
  195. RadToDeg()
  196. ----------
  197. Wandelt einen in Radiant angegebenen Winkel in Grad um.
  198. "RadToDeg(x)" entspricht also "x/Pi*180"
  199.  
  200. abs()
  201. -----
  202. Ergibt den Absolutwert oder Betrag des Argumentes.
  203.  
  204. arccos()
  205. --------
  206. Die Arcus-Cosinus-Funktion. Inverse Funktion des Cosinus.
  207. Der Betrag des Argumentes darf nicht größer als eins sein.
  208.  
  209. arcsin()
  210. --------
  211. Die Arcus-Sinus-Funktion. Inverse Funktion des Sinus.
  212. Der Betrag des Argumentes darf nicht größer als eins sein.
  213.  
  214. arctan()
  215. --------
  216. Die Arcus-Tanges-Funktion. Inverse Funktion des Tangens.
  217.  
  218. artanh()
  219. --------
  220. Die Arcus-Tangens-Hyperbolicus-Funktion. Inverse Funktion des Tanges-
  221. Hyperbolicus.
  222.  
  223. ceil()
  224. ------
  225. Liefert die nächste ganze Zahl die größer oder gleich dem Argument
  226. ist. Libraryfunktion, Name kommt von ceiling, engl. für Decke.
  227.  
  228. cos()
  229. -----
  230. Cosinus
  231.  
  232. cosh()
  233. ------
  234. Cosinus-Hyperbolicus
  235.  
  236. entier()
  237. --------
  238. Liefert die nächste ganze Zahl, die kleiner oder gleich dem Argument
  239. ist. Die Berechnung erfolgt über die OBERON-Funktion ENTIER(), daher
  240. muß der Betrag des Arguments kleiner als MAX(LONGINT) sein. Eigentlich
  241. sollte man lieber floor() benutzen, da man dann diese
  242. Bereicheinschränkung nicht beachten muß.
  243.  
  244. exp()
  245. -----
  246. Exponentialfunktion zur Basis e=2.7...
  247.  
  248. fac()
  249. -----
  250. Fakultät. Das Argument muß eine ganze Zahl zwischen 0 und 170 sein.
  251.  
  252. floor()
  253. -------
  254. Liefert die nächste ganze Zahl kleiner oder gleich dem Argument.
  255. Libraryfunktion, Name kommt von floor engl. Boden, siehe auch ceil().
  256.  
  257. id()
  258. ----
  259. Identität. id(x)=x
  260.  
  261. int()
  262. -----
  263. Liefert die nächste ganze Zahl, die dichter bei Null liegt als das
  264. Argument oder mit dem Argument identisch ist.
  265.  
  266. jump()
  267. ------
  268. (Heaviside'sche) Sprungfunktion. Liefert 1 für Argumente die größer
  269. als Null sind, sonst Null. Diese Funktion ist recht nützlich um
  270. bestimmte Stellen eines Funktionsgraphen auszublenden. In der
  271. Elektronik kommt sie unter dem namen E() vor, ich habe sie jump()
  272. genannt um Verwechslungen mit der Exponentialfunktion zu verhindern
  273. und um den Namen "E" für Zahlenwerte freizuhalten.
  274.  
  275. ln()
  276. ----
  277. Der natürliche Logarithmus zur Basis e=2.7...
  278.  
  279. log()
  280. -----
  281. Der Zehnerlogarithmus (dekadischer Logarithmus) zur Basis 10.
  282. log() ist identisch mit log10()
  283.  
  284. log2()
  285. ------
  286. Logarithmus zur Basis 2.
  287.  
  288. round()
  289. -------
  290. Rundung auf die nächste ganze Zahl.
  291. round(x) entspricht floor(x+0.5).
  292.  
  293. sin()
  294. -----
  295. Sinusfunktion. Argumente sind wie bei allen Winkelfunktionen auf
  296. Radiant bezogen.
  297.  
  298. sinh()
  299. ------
  300. Sinus-Hyperbolicus
  301.  
  302. sqr()
  303. -----
  304. Quadrat. sqr(x)=x*x
  305.  
  306. sqrt()
  307. ------
  308. Quadratwurzel. sqrt(x*x)=abs(x). Das Argument darf nicht negativ sein.
  309.  
  310. tan()
  311. -----
  312. Tangens.
  313.  
  314. tanh()
  315. ------
  316. Tangens Hyperbolicus
  317.  
  318. tentox()
  319. --------
  320. Ergibt 10^x
  321.  
  322. twotox()
  323. --------
  324. Ergibt 2^x
  325.  
  326.  
  327. Werte (engl. Values)
  328. --------------------
  329. Werte ist der Oberbegriff für Variablen und Konstanten. Wie schon
  330. gesagt darf ein mathematischer Ausdruck beliebige Namen enthalten.
  331. Statt 3.14 kann man in der Formel dann "Pi" einsetzen oder statt
  332. 2.9979E8 "Lichtgeschwindigkeit". Dadurch wird die Lesbarkeit von
  333. Formeln stark verbessert ohne die Effizienz der Berechnung zu
  334. verringern. Die Werte können, nachden sie definiert worden sind, in
  335. eine ASCII-Datei abgespeichert und aus dieser wieder eingelesen
  336. werden.
  337.  
  338.  
  339. Nun zu den Prozeduren im einzelnen:
  340. -----------------------------------
  341. PROCEDURE DefineValue(name:    ARRAY OF CHAR;
  342.                       value:   LONGREAL;
  343.                       trash:   BOOLEAN;
  344.                       comment: ARRAY OF CHAR): BOOLEAN;
  345.  
  346. Mit dieser Prozedur definiert man neue Werte oder ändert alte. name
  347. ist der Name des Wertes, der neu definiert oder geändert werden soll,
  348. value gibt den zugehörigen Zahlenwert an. Der Name darf fast alle über
  349. die Tastatur erreichbaren Zeichen enthalten, die Operatoren +,-
  350. ,*,/,^,:,= und Klammern sind allerdings nicht erlaubt. Außerdem darf
  351. der Name nicht mit einer Ziffer beginnen. Er darf aber Ziffern
  352. enthalten und auch mit einer Ziffer enden. Natürlich darf man für
  353. Werte nicht Namen verwenden, die schon für elementare Funktionen (sin,
  354. cos usw.) vergeben sind. Das Argument trash gibt an, ob dieser Wert
  355. später eventuell gespeichert werden soll oder nicht. Ist trash TRUE,
  356. so wird der Wert nicht gespeichert, ist trash gleich FALSE, so kann er
  357. später gespeichert werden. comment ist ein beliebiger Kommentar, der
  358. ebenfalls mit abgespeichert werden kann und z.B. angibt, auf welches
  359. Einheitensystem sich ein Wert bezieht oder ähnliches. Konnte der neue
  360. Wert definiert werden, so liefert die Prozedur TRUE als Resultat,
  361. anderenfalls FALSE. (Auch bei den folgenden Prozeduren bedeutet das
  362. Resultat TRUE, daß die betreffende Operation erfolgreich durchgeführt
  363. werden konnte) Momentan kann das Modul 2048 Werte verwalten.
  364.  
  365. PROCEDURE SaveValues(filename: ARRAY OF CHAR): BOOLEAN;
  366. -------------------------------------------------------
  367. Diese Prozedur speichert alle momentan existierenden Werte in eine
  368. Datei ab. Das betrifft die Werte, die entweder zuvor mit LoadValues()
  369. eingelesen oder mir DefineValue() definiert worden sind. Werte die
  370. zwar mit DefineValue() definiert wurden, bei denen aber trash=TRUE
  371. war, werden nicht abgespeichert. So kann man verhindern, daß
  372. irgendwelche Hilfsvariablen, die man eh nie wieder braucht, in der
  373. Datei Platz wegnehmen! Die Datei ist eine Textdatei, die mit jedem
  374. ASCII-Editor bearbeitet werden kann. Jede Zeile der Datei definiert
  375. einen Wert und sieht folgendermaßen aus:
  376.  
  377. <name> = <wert> ; [ Kommentar ]
  378.  
  379. Beispiel:
  380.  
  381. Lichtgeschwindigkeit = 2.9979E8 ; in m/s
  382.  
  383. Die Datei darf bis zu 2048 Zeilen haben, eine Zeile darf bis zu 256
  384. Zeichen lang sein.
  385.  
  386. PROCEDURE LoadValues(filename: ARRAY OF CHAR): BOOLEAN;
  387. -------------------------------------------------------
  388. Mit dieser Prozedur kann man die gespeicherten Werte wieder einlesen
  389. und sie dann in Formeln benutzen.
  390.  
  391. PROCEDURE Compile(str: ARRAY OF CHAR; VAR formula: Formula): BOOLEAN;
  392. ---------------------------------------------------------------------
  393. Compile() und Evaluate() sind die grundlegenden Prozeduren dieses
  394. Moduls. Compile() bekommt den mathematischen Ausdruck als String
  395. übergeben, überprüft ihn und wandelt ihn in den Datentyp Formula um.
  396. Die Variable von Typ Formula wird danach der Prozedur Evaluate()
  397. übergeben um die Berechnung (eventuell mehrfach mit veränderten
  398. Werten) durchzuführen. Gibt Compile() FALSE zurück, so enthält der
  399. String keine korrekte Formel, beispielsweise Klammerfehler oder
  400. undefinierte Werte, die man zuvor mit DefineValue() definieren muß.
  401. Wird TRUE zurückgegeben, kann man als nächstes Evaluate() aufrufen.
  402.  
  403. PROCEDURE Evaluate(VAR formula: Formula; VAR res: LONGREAL): BOOLEAN;
  404. ---------------------------------------------------------------------
  405. Diese Prozedur berechnet die zuvor mit Compile() bearbeitete Formel.
  406. Wird TRUE zurückgegeben, so enthält res das Resultat. Wird dagegen
  407. FALSE zurückgegeben, so ist ein Rechenfehler aufgetreten, etwa eine
  408. Division durch Null, und res daher ungültig. formula.error enthält
  409. dann die entsprechende Fehlernummer, und man kann mit
  410. io.WriteString(ErrorText(formula.error) eine Fehlermeldung ausgeben.
  411.  
  412. PROCEDURE GetIndex(name: ARRAY OF CHAR; VAR index: INTEGER): BOOLEAN;
  413. ---------------------------------------------------------------------
  414. Wie oben gesagt kann man mit DefineValue() Werte ändern. Dieser Weg
  415. ist aber nicht sehr schnell. Muß man einen Wert sehr oft verändern,
  416. beispielsweise bei einem Funktionsplotter, so gibt es einen besseren
  417. Weg. GetIndex(name,index) liefert den index des Wertes mit dem Namen
  418. name. Hat man den index ermittelt, so kann man den Wert mit
  419. ChangeValue() sehr schnell verändern. GetIndex() gibt TRUE zurück,
  420. wenn der Index ermittelt werden konnte. Wird FALSE zurückgegeben, so
  421. existert ein Wert mit dem Namen name nicht und index ist ungültig.
  422. ACHTUNG:  Durch Aufruf von DisposeAllValues() oder RemoveValue(name)
  423.           wird der index ungültig und muß mit GetIndex() neu ermittelt
  424.           werden. (Die übrigen Prozeduren machen den index nicht
  425.           ungültig)
  426.  
  427. PROCEDURE ChangeValue(index: INTEGER; value: LONGREAL);
  428. -------------------------------------------------------
  429. Hat man den index mit GetIndex() ermittelt, so kann man mit
  430. ChangeValue() einen Wert sehr schnell verändern. index ist der
  431. (mit GetIndex()) ermittelte index, value der neue Zahlenwert.
  432.  
  433. PROCEDURE FindValue(name: ARRAY OF CHAR; VAR x: LONGREAL;
  434.                     VAR comment: ARRAY OF CHAR): BOOLEAN;
  435. ---------------------------------------------------------
  436. Dies ist eine Prozedur, die man wohl nicht so oft benötigen wird. Mit
  437. ihr kann man nach einem Wert mit Namen name suchen. Existiert dieser
  438. Wert, so gibt die Prozedur TRUE zurück und x enthält den zugehörigen
  439. Zahlenwert und comment den eventuell vorhandenen Kommentar.
  440.  
  441. PROCEDURE RemoveValue(name: ARRAY OF CHAR): BOOLEAN;
  442. ----------------------------------------------------
  443. Hiermit kann man einen nicht mehr benötigten Wert vernichten. Er kann
  444. dann nicht mehr benutzt werden und wird auch nicht mehr abgespeichert.
  445. Eine zuvor mit Compile() erzeugte Formel, die diesen Wert enthält
  446. ist hiernach ungültig.
  447.  
  448. PROCEDURE DisposeAllValues;
  449. ---------------------------
  450. Löscht alle Werte. Hierdurch werden alle Formeln ungültig!
  451. Bevor man sie wieder mit Evaluate() berechnen kann müssen sie neu
  452. mit Compile() vorbereitet werden werden.
  453.  
  454. PROCEDURE WriteValues(p: WriteProc);
  455. ------------------------------------
  456. Ruft mit allen Werten die Prozedur p auf. p muß eine Prozedur sein,
  457. die als Parameter einen String übergeben bekommt, etwas
  458. io.WriteString().
  459.  
  460. PROCEDURE WriteFunctions(p: WriteProc);
  461. ---------------------------------------
  462. Ruft mit allen elementaren Funktionen die Prozedur p auf. p muß eine
  463. Prozedur sein, die als Parameter einen String übergeben bekommt, etwas
  464. io.WriteString().
  465.  
  466. Die letzen drei Prozeduren dienen nur zur Stringbearbeitung. Sie
  467. werden von den vorherigen Prozeduren benutzt und können eventuell von
  468. Nutzen sein, auch wenn sie mit den Berechnungen nichts zu tun haben.
  469.  
  470. PROCEDURE DeleteSpaces(VAR str: ARRAY OF CHAR);
  471. -----------------------------------------------
  472. Dies ist, wie auch die beiden folgenden Prozeduren eine reine
  473. Stringbearbeitungsprozedur. Es werden in str alle Leerzeichen, die an
  474. Anfang oder Ende des Strings stehen entfernt. Aus "   Hallo Stefan  "
  475. wird also "Hallo Stefan".
  476.  
  477. PROCEDURE Split(VAR str1, str2: ARRAY OF CHAR; c: CHAR): BOOLEAN;
  478. -----------------------------------------------------------------
  479.   (* splits str1 at position determined by c in str1 and str2      *)
  480.   (* If str1="" then str1:="" and str2:=""                         *)
  481.   (* IF c is the last  Char in str1 then str1:=str1-c and str2:="" *)
  482.   (* IF c is the first Char in str1 then str1:="" and str2:= str2-c*)
  483.   (* RETURNS TRUE if (c is in str1)                                *)
  484.  
  485. Hiermit kann man einen String in zwei Teile aufspalten. Gespalten wird
  486. an der Position, an der das Zeichen c das erste mal auftaucht. Wenn c
  487. nicht in str1 vorhanden ist wird FALSE zurückgegeben.
  488.  
  489. PROCEDURE Divide*(VAR input,name,expression,comment:ARRAY OF CHAR);
  490. -------------------------------------------------------------------
  491.   (*   input=      "pi =  2*arcsin(1) ; ~3.14"
  492.    ==> name=       "pi"
  493.    ==> expression= "2*arcsin(1)"
  494.    ==> comment=    "~3.14"
  495.   *)
  496.  
  497. Der String Input wird in name, expression und comment aufgespalten.
  498. Was vor dem Gleichheitszeichen steht wird als name angesehen, was
  499. hinter dem Semikolon steht als Kommentar.
  500.  
  501.  
  502. Zum Schluß noch ein paar Bemerkungen.
  503. -------------------------------------
  504. Der Quelltext wird zwar mitgeliefert, er dient aber hauptsächlich
  505. dokumentatorischen Zwecken und sollte nicht verändert werden. Wer
  506. Programme für einen A3000 entwickelt kann die Compileroptionen 68030
  507. und 882 setzen. Dadurch werden die Programme deutlich schneller,
  508. laufen dann aber auf Rechnern ohne Koprozessor nicht mehr. Dieses
  509. Modul braucht etwas Stack, da mathematische Ausdrücke rekursiv sind
  510. und auch rekursiv berechnet werden. Wenn es auf extreme
  511. Geschwindigkeit ankommt kann man dieses Modul auch ohne
  512. Überprüfungscode compilieren, wenn man allerdings den StackCheck
  513. abschaltet muß man sehr vorsichtig sein. Das Modul Formula fragt bei
  514. Programmstart mit Hilfe von OberonLib.StackCheck() ab, ob noch
  515. mindestens 10 KByte Stack frei sind. Das ist aber keine Garantie dafür
  516. daß nicht doch ein Stacküberlauf stattfinden kann. 14 kByte Stack
  517. reichen scheinbar aus, etwas mehr ist aber besser!
  518. Natürlich kann man mit mehreren Formeln gleichzeitig rechnen.
  519. Definiert man sich etwa die drei Variablen
  520. VAR f1,f2,f3:Formula.Formula;
  521. so kann man drei verschiedene Formeln mit
  522. Compile() vorbereiten und dann abwechselnd mit Evaluate() auswerten.
  523. Das Programm kann momentan 2048 Werte verwalten.
  524. Eine Formel darf maximal 1024 Elemente enthalten. Als
  525. Element gilt dabei jeweils ein Operator, ein Wert, eine
  526. elementare Funktion, eine Zahlenkonstante oder eine Klammer.
  527. "sin(Pi/123)*Epsilon" enthält also nur acht Elemente. Ich
  528. denke, daß man diese Grenzen wohl nie erreichen wird, aber
  529. bei Bedarf können diese Werte natürlich im Quelltext erhöht
  530. werden. Die Berechnungen erfolgen mit LONGREAL-Zahlen, so daß
  531. (Zwischen)-Ergebnisse bis zu 1.0E308 groß werden dürfen. Die
  532. Rechengenauigkeit ist mindestens 14-stellig.
  533.  
  534. Stefan Salewski, 26.4.92
  535.  
  536.  
  537.  
  538.  
  539.  
  540.  
  541.